package mapa;

import java.io.Serializable;
import java.util.Collection;
import java.util.HashMap;

import terrenos.Casilla;
import unidades.Unidad;

/**
 * Clase que permite gestionar los mapas
 *
 * @author Hasier Rodriguez
 */
public class Mapa implements Serializable {

    private transient Unidad[][] unidades;
    private Casilla[][] terreno;
    private int idMapa;
    private static HashMap<String, Mapa> mapas;

    /**
     * Devuelve el mapa solicitado
     * 
     * @param id El nombre del mapa
     * @return El mapa solicitado o null si no existe
     */
    public static Mapa getMapa(String id) {
        return mapas.get(id);
    }

    /**
     * Devuelve los nombres de todos los mapas
     * 
     * @return Collection<String> con los nombres de todos los mapas
     */
    public static Collection<String> getMapas() {
        return mapas.keySet();
    }

    /**
     * Establece todos los mapas disponibles
     * 
     * @param maps Todos los mapas existentes para el modulo que se esta ejecutando
     */
    public static void setMapas(HashMap<String, Mapa> maps) {
        mapas = maps;
    }

    /**
     * Inicializa un mapa con ancho x y alto y
     *
     * @param x El ancho del mapa
     * @param y El alto del mapa
     */
    public Mapa(int x, int y) {
        unidades = new Unidad[x][y];
        terreno = new Casilla[x][y];
    }

    /**
     * Devuelve el contenido de la casilla (una unidad o null)
     *
     * @param coord La coordenada en la que comprobar el contenido
     * @return Una unidad o null
     */
    public Unidad getContenidoCasilla(Coordenada coord) {
        return unidades[coord.getX()][coord.getY()];
    }

    /**
     * Devuelve la casilla (una casilla o null)
     *
     * @param coord La coordenada en la que comprobar el contenido
     * @return Una casilla o null
     */
    public Casilla getCasilla(Coordenada coord) {
        return terreno[coord.getX()][coord.getY()];
    }

    /**
     * Devuelve el array bidimensional que contiene los terrenos
     *
     * @return Un array bidimensional con los terrenos del mapa
     */
    public Casilla[][] getTerreno() {
        return terreno;
    }

    /**
     * Establece el array bidimensional de terrenos
     *
     * @param terreno El nuevo array bidimensional
     */
    public void setTerreno(Casilla[][] terreno) {
        this.terreno = terreno;
    }

    /**
     * Devuelve el array bidimensional que contiene las unidades
     *
     * @return Un array bidimensional con las unidades posicionadas en el mapa
     */
    public Unidad[][] getUnidades() {
        return unidades;
    }

    /**
     * Establece el array bidimensional de unidades
     *
     * @param terreno El nuevo array bidimensional
     */
    public void setUnidades(Unidad[][] unidades) {
        this.unidades = unidades;
    }

    /**
     * Devuelve la coordenada de más abajo y a la derecha del mapa
     * 
     * @return Un objeto de la clase Coordenada con la coordenada de abajo a la derecha del mapa
     */
    public Coordenada getCoordenadaMaxima() {
        if (terreno.length <= 0 || terreno[0].length <= 0) {
            throw new RuntimeException("El mapa es de tamaño 0");
        }
        return new Coordenada(terreno.length - 1, terreno[0].length - 1);
    }

    /**
     * Establece el contenido de una posición en el mapa. Si hay algún otro
     * objeto en esa posición será borrado
     *
     * @param u La unidad a colocar en el mapa. Puede ser null
     * @param c La coordenada en la que colocar la unidad
     * @throws NullPointerException si la coordenada es null
     * @throws ArrayIndexOutOfBoundsException si la coordenada no es correcta
     */
    public void setPosicion(Unidad u, Coordenada c) {
        if (c == null) {
            throw new NullPointerException("La coordenada no puede ser null");
        }
        unidades[c.getX()][c.getY()] = u;
    }

    /**
     * @return the idMapa
     */
    public int getIdMapa() {
        return idMapa;
    }

    /**
     * @param idMapa the idMapa to set
     */
    public void setIdMapa(int idMapa) {
        this.idMapa = idMapa;
    }
}
